

// For loops
const files = ["foo.txt ", ".bar", "   ", "baz.foo"];
let filePaths = [];

for (let file of files) {
  const fileName = file.trim();
  if (fileName) {
    const filePath = `~/cool_app/${fileName}`;
    filePaths.push(filePath);
  }
}

//  filePaths = 
//              ['~/cool_app/foo.txt',
//               '~/cool_app/.bar',
//               '~/cool_app/baz.foo']

// · for可以使用任何循环
// · 现在不太常见，因为函数式编程更受欢迎。
// · 控制迭代，例如跳过元素或早期returns。
// · 结果数组需要事先在循环外声明。
// · 使用Array.prototype.push()或 展开 ( ...) 运算符来添加元素。
// · O(N) 复杂性，每个元素将只迭代一次。




// Array reduce
const files = [ 'foo.txt ', '.bar', '   ', 'baz.foo' ];
const filePaths = files.reduce((acc, file) => {
  const fileName = file.trim();
  if(fileName) {
    const filePath = `~/cool_app/${fileName}`;
    acc.push(filePath);
  }
  return acc;
}, []);

//  filePaths = 
//              ['~/cool_app/foo.txt',
//               '~/cool_app/.bar',
//               '~/cool_app/baz.foo']

// · 第二个参数传递给函数的初始值。
// · 现在更常见，因为函数式编程更受欢迎。
// · 对迭代的控制较少，不能跳过元素或return提前。
// · 如有必要，可以与其他方法链接。
// · 使用Array.prototype.push()或 展开 ( ...) 运算符来添加元素。
// · O(N) 复杂性，每个元素将只迭代一次。



// Method chaining
const files = [ 'foo.txt ', '.bar', '   ', 'baz.foo' ];
const filePaths = files
  .map(file => file.trim())
  .filter(Boolean)
  .map(fileName => `~/cool_app/${fileName}`);

//  filePaths = 
//              ['~/cool_app/foo.txt',
//               '~/cool_app/.bar',
//               '~/cool_app/baz.foo']

// · 使用了Array.prototype.map()和Array.prototype.filter()。
// · 现在更常见，因为函数式编程更受欢迎。
// · 对迭代的控制较少，不能跳过元素或return提前。
// · 声明式，更易于阅读和重构，链可以根据需要增长。
// · 不能使用Array.prototype.push()或扩展 ( ...) 运算符。
// · O(cN)复杂性，c每个元素的迭代次数，（c：链的长度）。

